home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 February: Tool Chest / Dev.CD Feb 94.toast / Tool Chest / Development Platforms / AppsToGo / AppsToGo.src / DTS.Lib / AEConnect.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-18  |  20.6 KB  |  613 lines  |  [TEXT/MPS ]

  1. /*
  2. ** Apple Macintosh Developer Technical Support
  3. **
  4. ** Program:        DTS.Lib
  5. ** File:        AEConnect.c
  6. ** Written by:  Eric Soldan
  7. **
  8. ** Copyright © 1990-1991 Apple Computer, Inc.
  9. ** All rights reserved.
  10. **
  11. ** This is the custom AppleEvents code used for establishing a connection
  12. ** to another window.  DTS.Lib targets a specific window in an application,
  13. ** not just an application.  It also sends and returns more information
  14. ** about the connection, such as user name, zone, and machine.  This
  15. ** information is two-way, so each user can know who they are connected to.
  16. */
  17.  
  18. /* You may incorporate this sample code into your applications without
  19. ** restriction, though the sample code has been provided "AS IS" and the
  20. ** responsibility for its operation is 100% yours.  However, what you are
  21. ** not permitted to do is to redistribute the source as "DSC Sample Code"
  22. ** after having made changes. If you're going to re-distribute the source,
  23. ** we require that you make it clear in the source that the code was
  24. ** descended from Apple Sample Code, but that you've made changes. */
  25.  
  26.  
  27.  
  28. /*****************************************************************************/
  29.  
  30.  
  31.  
  32. #include "DTS.Lib2.h"
  33. #include "DTS.Lib.protos.h"
  34.  
  35. #ifndef __RESOURCES__
  36. #include <Resources.h>
  37. #endif
  38.  
  39. #ifndef THINK_C
  40. #ifndef __SYSEQU__
  41. #include <SysEqu.h>
  42. #endif
  43. #endif
  44.  
  45. #ifndef __TOOLUTILS__
  46. #include <ToolUtils.h>
  47. #endif
  48.  
  49.  
  50.  
  51. /*****************************************************************************/
  52.  
  53.  
  54.  
  55. extern OSType        gDocCreator;
  56. extern short        gMinVersion, gMaxVersion;
  57. extern Boolean        gHasAppleEvents;
  58. extern Cursor        *gCursorPtr;
  59.  
  60. static pascal OSErr        DoAEAnswer(AppleEvent *message, AppleEvent *reply, long refcon);
  61. static pascal OSErr        ReceiveConnect(AppleEvent *message, AppleEvent *reply, long refcon);
  62. static pascal OSErr        ReceiveConnectReply(AppleEvent *message, AppleEvent *reply);
  63. static pascal Boolean    AEPortFilter(LocationNamePtr locationName, PortInfoPtr thePortInfo);
  64.  
  65.  
  66.  
  67. /*****************************************************************************/
  68.  
  69.  
  70.  
  71. static AEHandler keywordsToInstall[] = {
  72.     { kCoreEventClass,        kAEAnswer,            (ProcPtr)DoAEAnswer },
  73.     { kCustomEventClass,    keyAppConnect,        (ProcPtr)ReceiveConnect },
  74. };        /* These are the custom AppleEvents. */
  75.  
  76.  
  77.  
  78. /*****************************************************************************/
  79. /*****************************************************************************/
  80.  
  81.  
  82.  
  83. /* Install the AppleEvents we use to establish a connection to a specific
  84. ** window.  This is done in addition to installing the required AppleEvents.
  85. ** InitAppleEvents, which installs the required AppleEvents, must be called
  86. ** first, since it sets up some global values. */
  87.  
  88. #pragma segment AppleEvents
  89. void    InitConnectAppleEvents(void)
  90. {
  91.     OSErr    err;
  92.     short    i;
  93.  
  94.     if (gHasAppleEvents) {
  95.         for (i = 0; i < (sizeof(keywordsToInstall) / sizeof(AEHandler)); ++i) {
  96.             err = AEInstallEventHandler(
  97.                 keywordsToInstall[i].theEventClass,    /* What class to install.  */
  98.                 keywordsToInstall[i].theEventID,    /* Keywords to install.    */
  99.                 keywordsToInstall[i].theHandler,    /* The AppleEvent handler. */
  100.                 0L,                                    /* Unused refcon.           */
  101.                 false                                /* Only for our app.       */
  102.             );
  103.  
  104.             if (err) {
  105.                 HCenteredAlert(rErrorAlert, nil, (ModalFilterProcPtr)AlertFilter);
  106.                 return;
  107.             }
  108.         }
  109.     }
  110. }
  111.  
  112.  
  113.  
  114. /*****************************************************************************/
  115.  
  116.  
  117.  
  118. /* This function handles the connect reply.  DTS.framework sends the connect request
  119. ** via kAEQueueReply.  This means that it doesn't necessarily come back immediately.
  120. ** (It actually comes back right away if it is connected to itself.)  The reply
  121. ** normally comes in via a high-level event.  Until this reply comes in, the
  122. ** connection isn't established.  When this reply does come in, the remaining
  123. ** information necessary to establish the connection to a particular window in
  124. ** the target application is recorded. */
  125.  
  126. #pragma segment AppleEvents
  127. static pascal OSErr    DoAEAnswer(AppleEvent *message, AppleEvent *reply, long refcon)
  128. {
  129. #pragma unused (refcon)
  130.  
  131.     gCursorPtr = nil;        /* Force re-calc of cursor region and cursor to use. */
  132.     return(ReceiveConnectReply(message, reply));
  133. }
  134.  
  135.  
  136.  
  137. /*****************************************************************************/
  138.  
  139.  
  140.  
  141. /* This is the function that is called to establish a connection to another
  142. ** DTS.framework-based application.  The "other" DTS.framework-based application is probably
  143. ** the same application on another machine.  This code does a bit more than simply connecting
  144. ** to another application.  It targets a specific window within that application.  It doesn't
  145. ** just target zone/machine/application, which is the granularity that AppleEvents gives you.
  146. ** It also passes back and forth some information that is kind of a pain to get, but
  147. ** is nice to have.  One such piece of information is the user name.  This needs to be
  148. ** sent.  It can't be determined from the message from an AppleEvent.  The sender sends
  149. ** the user name, and the receiver returns the remote user name.  The user name is
  150. ** placed in the document record for the window to be used if you wish. */
  151.  
  152. #pragma segment AppleEvents
  153. OSErr    SendConnect(FileRecHndl frHndl, char *theLocNBPType)
  154. {
  155.     AEAddressDesc    remoteLoc;
  156.     OSErr            err;
  157.     long            windTag[2], size;
  158.     char            hstate;
  159.     Ptr                ptr1, ptr2;
  160.     AppleEvent        theAevt, reply;
  161.     Str255            macText, appText;
  162.     Str32            remoteName;
  163.     Handle            remoteNameHndl;
  164.     OSType            sftype;
  165.     FSSpec            myFSS;
  166.  
  167.     theAevt.dataHandle = reply.dataHandle = nil;
  168.         /* Make sure disposing of the descriptors is okay in all cases.
  169.         ** theAevt and reply aren't necessarily instantiated correctly, so
  170.         ** we need to make sure that the dispose is safe, even if they aren't
  171.         ** valid.  theAevt isn't valid if MakeTarget returns an error.  If
  172.         ** MakeTarget returns an error, then AECreateAppleEvent isn't called
  173.         ** for theAevt.  Similarly, if AESend isn't called, reply isn't valid. */
  174.  
  175.     GetIndString(macText, rPPCText, sTitleText);
  176.     GetIndString(appText, rPPCText, sAppText);
  177.  
  178.     err = MakeTarget(&remoteLoc, false, kAEWaitReply, macText, appText,
  179.                     (PPCFilterProcPtr)AEPortFilter, theLocNBPType);
  180.         /* Generate the target for the remote user. */
  181.  
  182.     (*frHndl)->connect.remoteLoc    = remoteLoc;
  183.     (*frHndl)->connect.windowTag[0] = windTag[0] = (TickCount() & 0xFFFFFFFE);
  184.     (*frHndl)->connect.windowTag[1] = windTag[0];
  185.         /* The windTag fields are used to determine which window is the target
  186.         ** for an incomming AppleEvent.  windTag[0] for the application doing
  187.         ** the connecting will be even, and windTag[1] (the target's ID) will
  188.         ** be odd.  This prevents any accidental occurance where the windTag
  189.         ** fields are the same.  The target application will store these values
  190.         ** reversed.  Any incomming AppleEvent, from either application, will
  191.         ** invert these fields and then scan the window list looking for a window
  192.         ** that has the correct values in these fields.  If there is no such
  193.         ** window, then the window was closed at some point.  Initially, the sender
  194.         ** sets these values to be the same.  Until the sender receives a return
  195.         ** reply for the connect message, the windows aren't officially connected.
  196.         ** When the reply comes in, then the windTag[1] field is set to the reply's
  197.         ** return value. */
  198.  
  199.     if (!err) {        /* Create the AppleEvent... */
  200.         err = AECreateAppleEvent(        /* Create empty AppleEvent.       */
  201.             kCustomEventClass,            /*   Event class.               */
  202.             typeAppConnect,                /*   Event ID.                   */
  203.             &remoteLoc,                    /*   Address of receiving app. */
  204.             kAutoGenerateReturnID,        /*   This value causes the       */
  205.                                         /*   AppleEvent manager to       */
  206.                                         /*   assign a return ID that   */
  207.                                         /*   is unique to the session. */
  208.             kAnyTransactionID,            /*   Ignore transaction ID.       */
  209.             &theAevt                    /*   Location of event.           */
  210.         );
  211.     }
  212.  
  213.     if (!err) {
  214.         sftype = (*frHndl)->fileState.sfType;
  215.         err = AEPutParamPtr(    /* Add document type to AppleEvent. */
  216.             &theAevt,            /*   AppleEvent to add to. */
  217.             keySFType,            /*   AEKeyword.               */
  218.             typeLongInteger,    /*   Actual type.           */
  219.             (Ptr)&sftype,        /*   Pointer to the data.  */
  220.             sizeof(OSType)        /*   Size of the data.       */
  221.         );
  222.     }
  223.  
  224.     if (!err) {
  225.         myFSS = (*frHndl)->fileState.fss;
  226.         err = AEPutParamPtr(    /* Add document name (which is in the FSSpec) to AppleEvent. */
  227.             &theAevt,            /*   AppleEvent to add to. */
  228.             keyFSS,                /*   AEKeyword.               */
  229.             typeFSS,            /*   Desired type.           */
  230.             (Ptr)&myFSS,        /*   Pointer to the data.  */
  231.             sizeof(FSSpec)        /*   Size of the data.       */
  232.         );
  233.     }
  234.  
  235.     if (!err) {
  236.         hstate = HGetState((Handle)frHndl);
  237.         HLock((Handle)frHndl);
  238.         ptr1   = (Ptr)&((*frHndl)->connect);
  239.         ptr2   = (Ptr)&((*frHndl)->connect.endSendInfo);
  240.         size   = (long)ptr2 - (long)ptr1;
  241.         err = AEPutParamPtr(    /* Add file connect info to the AppleEvent. */
  242.             &theAevt,            /*   AppleEvent to add to.             */
  243.             keyAppConnect,        /*   AEKeyword.                         */
  244.             typeAppConnect,        /*   Desired type.                     */
  245.             ptr1,                /*   Pointer to the data to be sent. */
  246.             size                /*   Size of the data to be sent.     */
  247.         );
  248.         HSetState((Handle)frHndl, hstate);
  249.     }
  250.  
  251.     if (!err) {
  252.         remoteName[0] = 0;
  253.         if (remoteNameHndl = GetAppResource('STR ', -16096, nil))
  254.             pcpy(remoteName, (StringPtr)(*remoteNameHndl));
  255.         err = AEPutParamPtr(    /* Add user name to AppleEvent. */
  256.             &theAevt,            /*   AppleEvent to add to. */
  257.             keyPascal,            /*   AEKeyword.               */
  258.             typePascal,            /*   Desired type.           */
  259.             (Ptr)remoteName,    /*   Pointer to the data.  */
  260.             remoteName[0] + 1    /*   Size of the data.       */
  261.         );
  262.     }
  263.  
  264.     if (!err) {        /* If we have an AppleEvent ready to send... */
  265.         err = AESend(            /* Send AppleEvent.              */
  266.             &theAevt,            /*   Our Apple Event to send. */
  267.             &reply,                /*   We may have a reply.      */
  268.             kAEQueueReply,        /*   Type of reply.              */
  269.             kAENormalPriority,    /*   App. send priority.      */
  270.             0,                    /*   We aren't waiting.          */
  271.             nil,                /*   We aren't waiting.          */
  272.             nil                    /*   EventFilterProcPtr.      */
  273.         );
  274.     }
  275.     if (remoteLoc.descriptorType == typeProcessSerialNumber)
  276.         err = ReceiveConnectReply(&reply, &reply);
  277.             /* If we want a queue reply, and if we are sending to ourselves,
  278.             ** then we already have the reply.  Since we are sending to
  279.             ** ourselves, everything happens right away, even for queue reply, so
  280.             ** we must handle the connect reply here.  If we are sending to another
  281.             ** machine, then the reply will come in as a high-level event and we
  282.             ** will process it through the event loop. */
  283.  
  284.     AEDisposeDesc(&theAevt);
  285.     AEDisposeDesc(&reply);
  286.         /* Dispose of the descriptors, created or not.
  287.         ** If not created, no harm done by calling. */
  288.  
  289.     if (err) {
  290.         AEDisposeDesc(&remoteLoc);
  291.             /* If we didn't connect, get rid of the target descriptor.  If we
  292.             ** succeeded at connecting, then we keep the descriptor until the
  293.             ** connection is broken by the application. */
  294.  
  295.         (*frHndl)->connect.windowTag[0] = 0;
  296.         (*frHndl)->connect.windowTag[1] = 0;
  297.             /* Mark this window so that it will never be found if we somehow
  298.             ** do get an answer from the receiver, even after failure. */
  299.     }
  300.  
  301.     return(err);
  302. }
  303.  
  304.  
  305.  
  306. /*****************************************************************************/
  307.  
  308.  
  309.  
  310. /* This function receives a connect message from SendConnect.  The connection
  311. ** tasks that the receiver has to do are done here, such as opening a window for
  312. ** this end of the connection, etc.  It also returns whether or not it succeeded,
  313. ** and the user name.  Basically, it establishes the connection, while keeping
  314. ** some data as to whom it is connected to. */
  315.  
  316. #pragma segment AppleEvents
  317. static pascal OSErr    ReceiveConnect(AppleEvent *message, AppleEvent *reply, long refcon)
  318. {
  319. #pragma unused (refcon)
  320.  
  321.     OSErr            err;
  322.     FileRecHndl        frHndl;
  323.     char            hstate;
  324.     Ptr                ptr1, ptr2;
  325.     long            size, windTag[2];
  326.     AEAddressDesc    senderTarget;
  327.     DescType        ignoredType;
  328.     Size            ignoredSize;
  329.     OSType            sftype;
  330.     FSSpec            myFSS;
  331.     Str32            remoteZone, remoteMachine, remoteApplication, remoteName;
  332.     Handle            remoteNameHndl;
  333.     short            vers;
  334.  
  335.     err = AEGetParamPtr(    /* Get OSType to determine document type. */
  336.         message,            /*   The AppleEvent.            */
  337.         keySFType,            /*   AEKeyword                   */
  338.         typeLongInteger,    /*   Desired type.               */
  339.         &ignoredType,        /*   Type code.                   */
  340.         (Ptr)&sftype,        /*   Pointer to area for data. */ 
  341.         sizeof(OSType),        /*   Size of the data.           */
  342.         &ignoredSize        /*   Returned size of data.       */
  343.     );
  344.  
  345.     if (!err)
  346.         err = NewDocument(&frHndl, sftype, false);
  347.  
  348.     if (err) return(err);
  349.  
  350.     if (!err) {
  351.         hstate = HGetState((Handle)frHndl);
  352.         HLock((Handle)frHndl);
  353.         ptr1   = (Ptr)&((*frHndl)->connect);
  354.         ptr2   = (Ptr)&((*frHndl)->connect.endSendInfo);
  355.         size   = (long)ptr2 - (long)ptr1;
  356.         err = AEGetParamPtr(    /* Get connect info from the AppleEvent. */
  357.             message,            /*   The AppleEvent.            */
  358.             keyAppConnect,        /*   AEKeyword                   */
  359.             typeAppConnect,        /*   Desired type.               */
  360.             &ignoredType,        /*   Type code.                   */
  361.             ptr1,                /*   Pointer to area for data. */ 
  362.             size,                /*   Size of data area.           */
  363.             &ignoredSize        /*   Returned size of data.       */
  364.         );
  365.         HSetState((Handle)frHndl, hstate);
  366.     }
  367.  
  368.     if (!err) {
  369.         err = AEGetAttributeDesc(    /* Get address of sender.     */
  370.             message,                /*   Get address of sender from message. */
  371.             keyAddressAttr,            /*   We want an address.                 */
  372.             typeWildCard,            /*   We want the address of the sender.     */
  373.             &senderTarget            /*   Address of sender.                     */
  374.         );
  375.         if (!err) {
  376.             (*frHndl)->connect.remoteLoc = senderTarget;
  377.             err = AEGetParamPtr(    /* Get FSSpec (for document name) from AppleEvent. */
  378.                 message,            /*   The AppleEvent.            */
  379.                 keyFSS,                /*   AEKeyword                   */
  380.                 typeFSS,            /*   Desired type.               */
  381.                 &ignoredType,        /*   Type code.                   */
  382.                 (Ptr)&myFSS,        /*   Pointer to area for data. */ 
  383.                 sizeof(FSSpec),        /*   Size of the data.           */
  384.                 &ignoredSize        /*   Returned size of data.       */
  385.             );
  386.             if (!err)
  387.                 pcpy((*frHndl)->fileState.fss.name, (StringPtr)myFSS.name);
  388.         }
  389.         if (!err) {
  390.             err = AEGetParamPtr(    /* Get user name from AppleEvent. */
  391.                 message,            /*   The AppleEvent.            */
  392.                 keyPascal,            /*   AEKeyword                   */
  393.                 typePascal,            /*   Desired type.               */
  394.                 &ignoredType,        /*   Type code.                   */
  395.                 (Ptr)remoteName,    /*   Pointer to area for data. */ 
  396.                 sizeof(Str255),        /*   Size of the data.           */
  397.                 &ignoredSize        /*   Returned size of data.       */
  398.             );
  399.             (*frHndl)->connect.remoteName[0] = 0;
  400.             if (!err) {
  401.                 pcpy((*frHndl)->connect.remoteName, remoteName);
  402.                 remoteZone[0] = remoteMachine[0] = 0;
  403.                 GetTargetInfo(senderTarget, remoteZone, remoteMachine, remoteApplication);
  404.                 pcpy((*frHndl)->connect.remoteZone, remoteZone);
  405.                 pcpy((*frHndl)->connect.remoteMachine, remoteMachine);
  406.             }
  407.         }
  408.     }
  409.  
  410.     if (!err) {        /* If we got the remote user address... */
  411.  
  412.         (*frHndl)->connect.windowTag[0] = windTag[0] = (TickCount() | 0x01);
  413.         (*frHndl)->connect.connected = true;
  414.  
  415.         vers = (*frHndl)->d.doc.fhInfo.version;
  416.         if ((vers < gMinVersion) || (vers > gMaxVersion))
  417.             err = errAEWrongDataType;
  418.                 /* Incompatible file format. */
  419.  
  420.         if (!err) {
  421.             windTag[1] = (*frHndl)->connect.windowTag[1];
  422.             err = AEPutParamPtr(    /* Return receiver window ID. */
  423.                 reply,                /*   The AppleEvent.            */
  424.                 keyWindowTag,        /*   AEKeyword                   */
  425.                 typeDoubleLong,        /*   Type code.                   */
  426.                 (Ptr)&windTag[0],    /*   Pointer to area for data. */ 
  427.                 2 * sizeof(long)    /*   Size of data area.           */
  428.             );
  429.         }
  430.  
  431.         if (!err) {
  432.             remoteName[0] = 0;
  433.             if (remoteNameHndl = GetAppResource('STR ', -16096, nil))
  434.                 pcpy(remoteName, (StringPtr)(*remoteNameHndl));
  435.             err = AEPutParamPtr(    /* Return receiver user name. */
  436.                 reply,                /*   The AppleEvent.            */
  437.                 keyPascal,            /*   AEKeyword                   */
  438.                 typePascal,            /*   Type code.                   */
  439.                 (Ptr)remoteName,    /*   Pointer to area for data. */ 
  440.                 remoteName[0] + 1    /*   Size of data area.           */
  441.             );
  442.         }
  443.  
  444.         if (!err)
  445.             err = DoNewWindow(frHndl, nil, FrontWindow(), (WindowPtr)-1);
  446.                 /* If connecting worked, create a window for the document. */
  447.     }
  448.  
  449.     if (err)
  450.         DisposeDocument(frHndl);
  451.  
  452.     if (!err)
  453.         NotifyUser();
  454.  
  455.     return(err);
  456. }
  457.  
  458.  
  459.  
  460. /*****************************************************************************/
  461.  
  462.  
  463.  
  464. /* This function is called when you want to determine which window an AppleEvent
  465. ** is targeted for.  DTS.framework AppleEvents send two long values along with the AppleEvent
  466. ** to determine which window is the target window.  One of the longs is an ID for the
  467. ** sender, and the other is an ID for the receiver.  When a connection is established,
  468. ** these values are saved for both the sender and the receiver.  This allows the
  469. ** AppleEvent to be sent in either direction and still be targeted to the correct window.
  470. ** To find which window is the target, get these two longs out of the AppleEvent and then
  471. ** call GetAEWindow.  The first value is always the ID of the machine itself, and the
  472. ** second value is always the ID of the remote machine.  Due to this, you will need to
  473. ** reverse the order of these ID's for incomming DTS.framework AppleEvents. */
  474.  
  475. #pragma segment AppleEvents
  476. static pascal OSErr    ReceiveConnectReply(AppleEvent *message, AppleEvent *reply)
  477. {
  478. #pragma unused (reply)
  479.  
  480.     OSErr            err, replyErr;
  481.     DescType        actualType;
  482.     long            windTag[2], actualSize;
  483.     WindowPtr        window;
  484.     FileRecHndl        frHndl;
  485.     Str32            remoteZone, remoteMachine, remoteApplication, remoteName;
  486.  
  487.     err = AEGetParamPtr(        /* Check for a receiver error... */
  488.         message,                /*   The AppleEvent.            */
  489.         keyReplyErr,            /*   AEKeyword                   */
  490.         typeShortInteger,        /*   Desired type.               */
  491.         &actualType,            /*   Type code.                   */
  492.         (Ptr)&replyErr,            /*   Pointer to area for data. */ 
  493.         sizeof(short),            /*   Size of data area.           */
  494.         &actualSize                /*   Returned size of data.       */
  495.     );
  496.     if (err == errAEDescNotFound)
  497.         err = noErr;
  498.     else
  499.         if (!err)
  500.             err = replyErr;
  501.  
  502.     if (!err) {
  503.         err = AEGetParamPtr(    /* Get receiver window ID. */
  504.             message,            /*   The AppleEvent.            */
  505.             keyWindowTag,        /*   AEKeyword                   */
  506.             typeDoubleLong,        /*   Desired type.               */
  507.             &actualType,        /*   Type code.                   */
  508.             (Ptr)&windTag[0],    /*   Pointer to area for data. */ 
  509.             2 * sizeof(long),    /*   Size of data area.           */
  510.             &actualSize            /*   Returned size of data.       */
  511.         );
  512.     }
  513.  
  514.     if (!err) {        /* If we got the receiver window ID... */
  515.  
  516.         window = GetAEWindow(windTag[1], windTag[1]);
  517.             /* The ID's are still both ours, since this is where we
  518.             ** get the receiver's ID returned.  windTag[0] holds the
  519.             ** receiver's ID, and windTag[1] holds ours. */
  520.  
  521.         if (window) {
  522.             frHndl = (FileRecHndl)GetWRefCon(window);
  523.             if (!(*frHndl)->connect.connected) {
  524.                 err = AEGetParamPtr(
  525.                     message,            /* The AppleEvent.              */
  526.                     keyPascal,            /* AEKeyword                 */
  527.                     typePascal,            /* Desired type.             */
  528.                     &actualType,        /* Type code.                 */
  529.                     (Ptr)remoteName,    /* Pointer to area for data. */ 
  530.                     sizeof(Str255),        /* Size of data area.         */
  531.                     &actualSize            /* Returned size of data.     */
  532.                 );
  533.  
  534.                 (*frHndl)->connect.remoteName[0] = 0;
  535.                 if (!err) {        /* Connection is for sure, so remember what we need. */
  536.                     (*frHndl)->connect.windowTag[1] = windTag[0];
  537.                     pcpy((*frHndl)->connect.remoteName, remoteName);
  538.                     GetTargetInfo((*frHndl)->connect.remoteLoc,
  539.                                   remoteZone, remoteMachine, remoteApplication);
  540.                     pcpy((*frHndl)->connect.remoteZone, remoteZone);
  541.                     pcpy((*frHndl)->connect.remoteMachine, remoteMachine);
  542.                     (*frHndl)->connect.connected = true;
  543.                 }
  544.                 else
  545.                     (*frHndl)->connect.windowTag[0] = (*frHndl)->connect.windowTag[1] = 0;
  546.             }
  547.         }
  548.     }
  549.  
  550.     return(err);
  551. }
  552.  
  553.  
  554.  
  555. /*****************************************************************************/
  556.  
  557.  
  558.  
  559. /* Find the window with the specified window ID's. */
  560.  
  561. #pragma segment AppleEvents
  562. WindowPtr    GetAEWindow(long windTag_0, long windTag_1)
  563. {
  564.     WindowPeek    window;
  565.     FileRecHndl    frHndl;
  566.  
  567. #ifdef __SYSEQU__
  568.     for (window = *(WindowPeek *)WindowList; window; window = window->nextWindow) {
  569. #else
  570.     for (window = (WindowPeek)WindowList; window; window = window->nextWindow) {
  571. #endif
  572.         if (IsAppWindow((WindowPtr)window)) {
  573.             frHndl = (FileRecHndl)GetWRefCon((WindowPtr)window);
  574.             if (
  575.                 ((*frHndl)->connect.windowTag[0] == windTag_0) &&
  576.                 ((*frHndl)->connect.windowTag[1] == windTag_1)
  577.             ) return((WindowPtr)window);
  578.         }
  579.     }
  580.  
  581.     return(nil);
  582. }
  583.  
  584.  
  585.  
  586. /*****************************************************************************/
  587.  
  588.  
  589.  
  590. /* This function doesn't allow the PPCBrowser to display any applications other
  591. ** than the designated application(s). */
  592.  
  593. #pragma segment AppleEvents
  594. static pascal Boolean    AEPortFilter(LocationNamePtr locationName, PortInfoPtr thePortInfo)
  595. {
  596. #pragma unused (locationName)
  597.  
  598.     OSType    type;
  599.  
  600.     if (thePortInfo->name.portKindSelector == ppcByString) {
  601.         BlockMove(thePortInfo->name.u.portTypeStr + 1, (Ptr)&type, 4);
  602.             /* The BlockMove is so that we don't get an address error
  603.             ** on a 68000-based machine due to referencing a long at
  604.             ** an odd-address. */
  605.         if (type == gDocCreator) return(true);
  606.     }
  607.  
  608.     return(false);
  609. }
  610.  
  611.  
  612.  
  613.